home *** CD-ROM | disk | FTP | other *** search
- program fft;
- {$i typedef.sys}
- {$i graphix.sys}
- {$i kernel.sys}
- {$i axis.hgh}
- {$i polygon.hgh}
-
- type
- cmpl = record
- re,im :real
- end;
-
- bigstr = string[12];
- range = array[1..256] of cmpl;
- var
- filename,nstr,fileout :bigstr;
- filnam,fiout :string[8];
- xform :string[25];
- inverse,output :char;
- npoints,invt,d :integer;
- rd :range;
-
- procedure FindWorld(i:integer;
- A:PlotArray;
- NPoints:integer);
-
- var XMax,YMax,XMin,YMin:real;
- j:integer;
-
- begin
- NPoints:=abs(NPoints);
- if NPoints>=2 then
- if i in [1..MaxWorldsGlb] then
- begin
- XMax:=A[1,1];
- YMax:=A[1,2];
- XMin:=XMax;
- YMin:=YMax;
- for j:=2 to NPoints do
- begin
- if A[j,1]>XMax then XMax:=A[j,1]
- else if A[j,1]<XMin then XMin:=A[j,1];
- if A[j,2]>YMax then YMax:=A[j,2]
- else if A[j,2]<YMin then YMin:=A[j,2];
- end;
- if (ymax=ymin) and (ymax=0) then begin
- ymax:=1;
- ymin:=0
- end
- else ymin:=0;
- DefineWorld(i,XMin,YMin,XMax,YMax);
- SelectWorld(i);
- end
- else error(7,2)
- else error(7,4);
- end;
-
- procedure readdata(filename:bigstr;var d :range;var a:integer);
-
- {range and bigstr are set up in the TYPE identifier
- range = array[1..?] of real
- bigstr = string[12]
- a returns the transform length or file size}
-
- type
- data =
- record
- w,z :real;
- end;
- var
- index :integer;
- xy :array[1..256] of data;
- datafile :file of data;
- begin
- assign(datafile,filename);
- reset(datafile);
- a:=filesize(datafile);
- for index:=1 to a do begin
- read(datafile,xy[index]);
- with d[index] do begin
- re:=xy[index].w;
- im:=xy[index].z;
- end;
- end;
- close(datafile);
- end;
-
- procedure writedata(filename:bigstr;var d:range;var a:integer);
- type
- data =
- record
- w,z :real;
- end;
- var
- index :integer;
- xy :array[1..256] of data;
- datafile :file of data;
- begin
- assign(datafile,filename);
- rewrite(datafile);
- for index:=1 to a do begin
- with xy[index] do begin
- w:=d[index].re;
- z:=d[index].im;
- end;
- write(datafile,xy[index]);
- end;
- close(datafile);
- end;
-
- PROCEDURE PLOT(inv,NOPTS :INTEGER; XK :RANGE);
-
- VAR
- HRZ:INTEGER;
- b,a:PlotArray;
- key:char;
- titleRE,titleIM:string[40];
-
- BEGIN
- if inv=1 then begin
- titlere:='Direct Transform --- Amplitude Response';
- titleim:='Direct Transform --- Phase Response';
- FOR HRZ:=1 TO NOPTS DO
- BEGIN
- a[HRZ,1]:=hrz-1;
- b[HRZ,1]:=hrz-1;
- a[HRZ,2]:=sqrt(sqr(XK[HRZ].RE)+sqr(xk[hrz].im));
- b[HRZ,2]:=arctan(XK[HRZ].IM/xk[hrz].re);
- END;
- end
- else begin
- titlere:='Inverse Transform --- Real Part';
- titleim:='Inverse Transform --- Imaginary Part';
- FOR HRZ:=1 TO NOPTS DO
- BEGIN
- a[HRZ,1]:=hrz-1;
- b[HRZ,1]:=hrz-1;
- a[HRZ,2]:=xk[hrz].re;
- b[HRZ,2]:=xk[hrz].im;
- END;
- end;
-
- initgraphic;
- CLEARSCREEN;
- definewindow(1,0,0,xmaxglb,ymaxglb-20);
- definewindow(2,0,0,xmaxglb,ymaxglb-20);
- defineworld(2,b[1,1],-(pi/2),b[nopts,1],(pi/2));
-
- DEFINEHEADER(1,titlere);
- defineheader(2,titleim);
- selectwindow(1);
- setheaderon;
-
- findworld(1,a,nopts); {automatically executes defineworld}
-
- selectwindow(1);
- drawborder;
-
- drawaxis(7,5,0,0,0,0,0,0,false);
- drawpolygon(a,1,nopts,0,2,0);
- GOTOXY(1,25);
- WRITELN('Press any key to continue...');
- repeat until keypressed;
-
- clearscreen;
- selectworld(2);
- selectwindow(2);
- drawborder;
-
- drawaxis(7,5,0,0,0,0,0,0,false);
- drawpolygon(b,1,nopts,0,2,0);
- repeat
- GOTOXY(1,25);
- WRITE('Press C to continue...');
- read(kbd,key);
- until key in ['c','C'];
-
- leavegraphic;
- end;
-
- procedure fft(inv,n:integer;var ft:range);
-
- {range is set up in the TYPE identifier and is = array[1..?] of real
- inv = 1 if direct transform and =-1 for inverse
- n = transform length power of 2}
-
- var
- le,ip,m,i,l,nm1,j,t,le1 :integer;
- ur,ui,tr,ti,tmpr,tmpi,nv2,k :real;
-
- begin
- m:=round(ln(n)/ln(2));
- if abs(m-int(m))=0 then begin
- nv2:=n/2;
- nm1:=n-1;
- j:=1;
- for i:=1 to nm1 do begin
- if i<j then begin
- tmpr:=ft[j].re;tmpi:=ft[j].im;
- ft[j].re:=ft[i].re;ft[j].im:=ft[i].im;
- ft[i].re:=tmpr;ft[i].im:=tmpi;
- end;
- k:=nv2;
- while k<j do begin
- j:=round(j-k);
- k:=k/2;
- end;
- j:=round(j+k);
- end;
- for l:=1 to m do begin
- le:=1;
- for t:=1 to l do
- le:=le*2;
- le1:=round(le/2);
- ur:=1;ui:=0;
- for j:=1 to le1 do begin
- i:=j;
- while i<=n do begin
- ip:=i+le1;
- tr:=ft[ip].re*ur-ft[ip].im*ui;ti:=ft[ip].im*ur+ft[ip].re*ui;
- ft[ip].re:=ft[i].re-tr;ft[ip].im:=ft[i].im-ti;
- ft[i].re:=ft[i].re+tr;ft[i].im:=ft[i].im+ti;
- i:=i+le;
- end;
- ur:=cos(pi*j/le1);ui:=-inv*sin(pi*j/le1);
- end;
- end;
- if inv=-1 then begin
- for i:=1 to n do begin
- ft[i].re:=ft[i].re/n;
- ft[i].im:=ft[i].im/n;
- end;
- end;
- end;
- end;
-
- begin
- clrscr;
- gotoxy(29,1);writeln('Fast Fourier Transform');
- gotoxy(39,3);writeln('by');
- gotoxy(31,4);writeln('Michael F. Griffin');
- writeln;writeln;writeln;
- gotoxy(19,6);writeln('*----------------------------------------*');
- gotoxy(8,8);writeln('- All file names are assumed to have .DAT as the extension.');
- gotoxy(8,9);writeln('- Output goes to either a file or a printer.');
- writeln;writeln;
- write('Enter data file name w/o extension : ');
- readln(filnam);
- filename:=filnam+'.dat';
- writeln('Input File name ==> : ',filename);
- write('Do you want a direct transform <Y/N>?');
- read(kbd,inverse);writeln;
- if (inverse='Y') or (inverse='y') then begin
- xform:='Direct Fourier Transform';
- invt:=1
- end
- else begin
- xform:='Inverse Fourier Transform';
- invt:=-1
- end;
- write('Do you want the output to a file <Y/N>?');
- read(kbd,output);writeln;
- if (output='Y') or (output='y') then begin
- write('Enter output data file name w/o extension : ');
- readln(fiout);
- fileout:=fiout+'.dat';
- writeln('Output File name ==> : ',fileout);
- end;
- readdata(filename,rd,npoints);
- fft(invt,npoints,rd);
- plot(invt,npoints,rd);
- if (output='Y') or (output='y') then
- writedata(fileout,rd,npoints)
- else begin
- writeln(lst,xform);writeln(lst);
- str(npoints,nstr);
- for d:=1 to npoints do
- writeln(lst,'(',d:length(nstr),')',rd[d].re,rd[d].im)
- end;
- end.
-
-